package com.lagou.rocketmq.controller;

import com.lagou.rocketmq.dao.OrderDao;
import com.lagou.rocketmq.model.Orders;
import com.lagou.rocketmq.service.GoodsQuantityServiceImpl;
import com.lagou.rocketmq.util.lock.RedisLockHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName OrderController
 * @Description TODO
 * @Author xsq
 * @Date 2020/11/25 14:49
 **/
@Slf4j
@RestController
@RequestMapping("/order")
public class OrderController {

    private final static String QUANTITY = "quantity";


    private final static String SECKILL_KEY = "seckill_key";
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private RedisLockHandler redisLockHandler;


    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private GoodsQuantityServiceImpl goodsQuantityServiceImpl;

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private RedissonClient redissonClient;
    /**
     * 比较完善的秒杀还要进行url动态化,ip限流,前端限流,cdn加速,秒杀是否开始的判断等,这里比较简略,
     * 比较流行的秒杀解决高并发的方法一种是用分布式锁,一种是用lua脚本,这里采用redis分布式锁
     */
    @RequestMapping("/click")
    public  Boolean order() {
        //判断是否预加载了库存到redis,没有就进行加载(
        // 正常应该通过定时任务或者运维来加载,这里为了简便就直接在请求接口加载了)
      /*  goodsQuantityServiceImpl.initGoodsQuantity();*/
        //随机订单号
        String id = UUID.randomUUID().toString();
        try {
            //对该订单进行redis加锁
            redisLockHandler.lock(SECKILL_KEY);
            Integer quantityLock = (Integer) redisTemplate.opsForValue().get(QUANTITY);
            if (quantityLock <= 0) {
                log.info("手机已卖完");
                return false;
            }
            //redis库存减去1
            redisTemplate.opsForValue().decrement(QUANTITY);
            rocketMQTemplate.convertAndSend("seckill", id);
            return true;
        } catch (Exception e) {
            log.error("OrderController order 秒杀失败{}", id);
            return false;
        } finally {
            redisLockHandler.unLock(SECKILL_KEY);
        }

    }

    @PostMapping("pay")
    public String pay(String id) {
        //获取订单信息
        Orders orders = orderDao.getOrderByOrderId(id);
        if (orders.getOrderStatus() == 2) {
            return "订单支付超时";
        } else if (orders.getOrderStatus() == 1) {
            return "订单已支付";
        } else if (orders.getOrderStatus() == 0) {
            orders.setOrderStatus(1);
            orderDao.save(orders);
            return "订单支付成功" + id;
        }
        return null;
    }


    @RequestMapping("/test")
    public void test() {
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        for (int i = 0; i < 200; i++) {
            cachedThreadPool.execute(() -> {
                // 模拟500个并发进行下单处理
                order();
            });
        }
    }

}
